#include "PopupClientThread.hpp"
#include "PopupSettings.hpp"

using namespace Popup;
using namespace std;

//=============================================================================
// Thread routine
//=============================================================================

void PopupClientThread::run()
{
  while (true)
  {
    if (m_tryToConnect)
    {
      ConnectionEcode _rc = m_client->connect(
          m_server, m_port, m_login, m_password,
          m_register);

      switch (_rc) {
        // Errors due to connection parameters
        case POPUP_CONNECTION_ERR_USER_ALREADY_CONNECTED:
        case POPUP_CONNECTION_ERR_UNKNOWN_USER:
        case POPUP_CONNECTION_ERR_INVALID_PASSWORD:
        case POPUP_CONNECTION_ERR_EMPTY_LOGIN:
        case POPUP_CONNECTION_ERR_LOGIN_ALREADY_EXISTS:
          emit signal_badConnectionParams(_rc);
          m_tryToConnect = false;
          break;

        // Errors which are due to server
        // => we'll keep trying to connect
        case POPUP_CONNECTION_ERR_UNKNOWN:
        case POPUP_CONNECTION_ERR_SERVER_DOWN:
        case POPUP_CONNECTION_ERR_HANDSHAKE_FAILED:
        case POPUP_CONNECTION_ERR_SQLITE:
        default:
          break;
      }
    }
    sleep(2);
  }
}

//=============================================================================
// Connection parameters setup
//=============================================================================

void PopupClientThread::slot_setConnectionParams(const QString & p_login,
                                           const QString & p_password,
                                           const QString & p_server,
                                           int p_port, bool p_register)
{
  m_login    = p_login.toStdString();
  m_password = p_password.toStdString();
  m_server   = p_server.toStdString();
  m_port     = (unsigned short) p_port;
  m_register = p_register;
  m_tryToConnect = true;
}

//=============================================================================
// Slots
//=============================================================================

void PopupClientThread::slot_disconnect()
{
  m_client->disconnect();
  m_tryToConnect = false;
}

void PopupClientThread::slot_restartClient()
{
  m_client->disconnect();
}
//----------------------------------------------------------

void PopupClientThread::slot_sendMessage(UserMessage *p_message)
{
  m_client->sendMessage(*p_message);
}
//----------------------------------------------------------

void PopupClientThread::slot_sendMessageReaction(RateUserMessage *p_reaction)
{
  m_client->sendMessageReaction(*p_reaction);
}
//----------------------------------------------------------

void PopupClientThread::slot_localUserUpdated(const User *p_me,
                                              unsigned short p_updateMask)
{
  m_client->notifyUserUpdate(p_me, p_updateMask);
}
//----------------------------------------------------------

void PopupClientThread::slot_submitCanvass(Canvass *p_canvass)
{
  m_client->submitCanvass(*p_canvass);
}
//----------------------------------------------------------

void PopupClientThread::slot_sendVote(Vote *p_vote)
{
  m_client->sendVote(*p_vote);
}
//----------------------------------------------------------

void PopupClientThread::slot_sendInvitation(ThreadInvitation *p_invitation)
{
  m_client->sendInvitation(*p_invitation);
}

//=============================================================================
// Implementation of PopupClientUI
//=============================================================================

void PopupClientThread::onFileTransferUpdate(const FileTransfer & p_transfer)
{
  emit signal_updateFileTransferProgress(p_transfer);
}
//----------------------------------------------------------

void PopupClientThread::onMessageReceived(const UserMessage & p_message)
{
  emit signal_messageReceived(p_message);
}
//----------------------------------------------------------

void PopupClientThread::onMessageSent(const UserMessage & p_message)
{
  emit signal_messageSent(p_message);
}
//----------------------------------------------------------

void PopupClientThread::onMessageReactionReceived(
    const RateUserMessage & p_reaction)
{
  emit signal_messageReactionReceived(p_reaction);
}
//----------------------------------------------------------

void PopupClientThread::onConnectionUpdate(bool p_connected,
                                           const User & p_myself,
                                           SessionID p_sessionID)
{
  emit signal_onConnectionUpdate(p_connected, p_myself, p_sessionID);
}
//----------------------------------------------------------

void PopupClientThread::onUserUpdate(const User & p_user,
                                     unsigned short p_updateMask,
                                     bool p_isNewUser)
{
  emit signal_updateUser(p_user, p_updateMask, p_isNewUser);
}
//----------------------------------------------------------

void PopupClientThread::onUserStatisticsUpdate(UserID p_userID,
                                               UserStatistics & p_stats)
{
  emit signal_updateUserStatistics(p_userID, p_stats);
}
//----------------------------------------------------------

string PopupClientThread::getTemporaryDir()
{
  return PopupSettings::instance()->temporaryDirectory().toStdString();
}
//----------------------------------------------------------

string PopupClientThread::getResourceDir()
{
  return PopupSettings::instance()->resourceDirectory().toStdString();
}
//----------------------------------------------------------

void PopupClientThread::onOpinionRequested(const Canvass & p_canvass)
{
  emit signal_onOpinionRequested(p_canvass);
}
//----------------------------------------------------------

void PopupClientThread::onVoteReceived(const Vote & p_vote)
{
  emit signal_onVoteReceived(p_vote);
}
//----------------------------------------------------------

void PopupClientThread::onInvitationReceived(const ThreadInvitation & p_invitation)
{
  emit signal_onInvitationReceived(p_invitation);
}
